<?php

/** Dataxi menu bar
 *  This code is licensed under GPL2.
 *  See LICENSE or www.gnu.org for more details.
 *  @author Henri Ranki
 */

include_once("sodebug.php");
include_once("sogeneric.php");
include_once("soinifiles.php");
include_once("sostreams.php");

include_once("dzgeneric.php");

/** Menu related constants */
define(DZMP_LINK, "source");  /** Source file menu property key */


/** A class that contains the structure of the Dataxi application menu
 *  a menu.ini (default) is read in and the menu is constructed acording
 *  to that. ini-file could be overidden in constructor
 *  @param array/soSet $MenuStruct An array of main menu (dropdown boxes).
 *      Each item  contains a set of sub items.
 */
class dzMenu {
    var $MenuStruct;
    var $__Widths;      /** soSet/int Widths of the menus in characters. */


    /** Gets menu ini as a string.
     *  Reads in menu, modifies form paths and returns it as a string.
     *  @param string $MenuName Menu name ro read in.
     *  @return string Menu ini string
     */
    function __readMenu($MenuName, $FormsPath) {
        /* Read the menu definition from the ini file */
        $ini = new soIni($MenuName);
        if ($ini->Error) {
            dzSysError("Could Not find menu definition from $MenuName");
        } // if

        $sect_count= $ini->getSectionCount();
        for ($s = 0; $s < $sect_count; $s++) {
            $item_no = 0;
            $value = $ini->getSetValue($s, $item_no, DZMP_LINK);
            while (!$ini->Error) {
                $action = dzParseMenuTarget($value);
                switch ($action->Target) {
                    case DZMT_NALLE:
                        $split = soSplitStr($value, "://", 1, 1);
                        $value = $split[0].$FormsPath.$split[1];
                        $value = str_replace("~", dzGetMainScriptPath(), $value);
                        break;

                    case DZMT_EXT_WINDOW:
                        $value = $action->Stream;
                        break;
                } // switch

                $ini->setSetValue($ini->CurrentSectionName,
                                  $ini->getCurrentKeyName(),
                                  DZMP_LINK, $value);
                $value = $ini->getSetValue($s, ++$item_no, DZMP_LINK);
            }; // while
        }; // for

        return $ini->getIniString();
    } // __readMenu


    /** Sets up menu
     *  Reads in the ini-files and initializes __MenuStruct property. You
     *  can give a parameter that specifies where to read menu information.
     *  Default is menu.ini.
     *  @param array/string $UserGroups Groups the users belongs to
     *  @param int $UserLevel The user level
     *  @param string $MenuName The stream where the menu definition is read
     *  @param string Language Language code
     */
    function __setupMenu($UserGroups, $UserLevel, $MenuName,
                         $Language = "default") {
        if ($Language == "") $Language = "default";

        /* Get the user level where starts admin users */
        $admin_level = dzGetIniItem(DZIS_SYS,
                                     DZID_ADMIN_USER_LEVEL,
                                     "dataxi");

        $MenuName = "file://".$MenuName.".";
        $this->MenuStruct = array();
        $this->__Widths = new soSet();

        /* Read the menu definition from the ini file */
        $forms_path = dzGetIniPath(DZID_FORM_SOURCE_FOLDER)."/";
        $ini_str = $this->__readMenu($MenuName."ini", $forms_path);

        /* Read the translations from the file */
        $transl_ini_stream = new soInputStream($MenuName."txt");
        $transl_ini_str = $transl_ini_stream->Data;

        /* Add system menu, if user is admin */
        if ($UserLevel >= $admin_level) {
            $sys_folder = dzGetDataxiPath();
            $sys_menu_file = "file://$sys_folder/".
                             dzGetIniItem(DZIS_SYS,
                             DZID_ADMIN_MENU_FILE,
                             "dataxi");
            $forms_path = "$sys_folder/".DZIS_DIALOGS;
            $ini_str .= "\n".$this->__readMenu($sys_menu_file,
                                               $forms_path."/");

            /* Read the translations from the file */
            $dot_pos = soLocateStr($sys_menu_file, ".", -1);
            $sys_transl_ini = substr($sys_menu_file, 0, $dot_pos +1)."txt";
            $transl_ini_stream = new soInputStream($sys_transl_ini);
            if ($transl_ini_stream->Error) {
                dzSysError("Could not find system menu translations in: ".
                           "$sys_transl_ini");
            } // if
            $transl_ini_str .= "\n".$transl_ini_stream->Data;
        }; // if ($UserLevel > $admin_level)

        /* Read the Ini stream */
        $iniFile = new soIniData($ini_str);
        $translations = new soIniData($transl_ini_str);

        /* Strict menu access? Check it from app ini */
        $strict_access = dzGetIniItem(DZIS_GENERAL,
                                      "strict_menu_access", "app", "bool");

        $sectionCount = $iniFile->getSectionCount();
        for ($c = 0; $c < $sectionCount; $c++) {

            /* Check group rights of a menu */
            $groups = soExplode($iniFile->getValue($c, "groups"), ",");
            if (!count($groups)) {
                $group_ok = (!$strict_access);
                $key_no = 0;
            } else {
                $group_ok = soInArray($limit_groups, $UserGroups);
                $key_no = 1;
            }; // if

            /* Check user level rights for a menu */
            $level = $iniFile->getValue($c, "user_level");
            if (!$level) {
                $level_ok = (!$strict_access);
            } else {
                $level_ok = ($UserLevel >= $level);
            }; // if

            /* Admin has access to everything */
            if ($UserLevel >= $admin_level) {
                $group_ok = 1;
                $level_ok = 1;
            }; // if

            /* Only add an menu enty if group & level are accepted */
            if ($group_ok && $level_ok) {
                $menu_no = 1;
                $max_width = -1;
                $itemSet = new soSet();
                $iniFile->findSection($c);
                $section = $iniFile->CurrentSectionName;
                do {
                    $prop_set = $iniFile->getValueSet($c, $key_no);
                    $prop_name = $iniFile->getCurrentKeyName();
                    $out_name = $translations->getSetValue($section,
                                                           $prop_name,
                                                           $Language);
                    if ($out_name == "") {
                        $out_name = $translations->getSetValue($section,
                                                               $prop_name,
                                                               "default");
                    };
                    if ($out_name == "") $out_name = $prop_name;

                    $source = $prop_set->getItem(DZMP_LINK);
                    $max_width = max($max_width, strlen($out_name));
                    if ((!$iniFile->getError()) && ($source != "")) {
                        /* Check group rights of a menu entry */
                        $groups = soExplode($prop_set->getItem("groups"), ",");
                        if (!count($groups)) {
                            $group_ok = (!$strict_access);
                        } else {
                            $group_ok = soInArray($limit_groups, $UserGroups);
                        }; // if

                        /* Check user level rights for a menu entry */
                        $level = $prop_set->getItem($c, "user_level");
                        if (!$level) {
                            $level_ok = (!$strict_access);
                        } else {
                            $level_ok = ($UserLevel >= $level);
                        }; // if

                        /* Admin has access to everything */
                        if ($UserLevel >= $admin_level) {
                            $group_ok = 1;
                            $level_ok = 1;
                        }; // if

                        if ($group_ok && $level_ok) {
                            $itemSet->setItem(($menu_no++)." ".$out_name,
                                               $source);
                        }; // if user_level >
                    }; // if
                    $key_no++;
                } while (!$iniFile->getError());
                $out_section = $translations->getSetValue($section, "head",
                                                          $Language);
                if ($out_section == "") {
                    $out_section = $translations->getSetValue($section, "head",
                                                              "default");
                };
                if ($out_section == "") $out_section = $section;
                $this->__Widths->setItem($out_section, $max_width);
                $this->MenuStruct[$out_section] = $itemSet;
            } // if $userlevel

        } // for
    } // __setupMenu


    /** Create menu
     *  Makes the script that is used to construct the Dataz menu bar.
     *  The user level is considered. Menu.ini defines the user level limits
     *  for each drop down box. The users level must be equal or creater than
     *  the limit to have that dorp down box to be shown in the menu.
     *  @param bool true if the session is suspended
     *  @param string $UserName Users name (for displaying only)
     *  @param array/atring $UserGroups An array of user's groups
     *  @param int $UserLevel The users level who will receive the menu.
     *  @param string $MenuName The stream where the menu definition is read
     *  @param string $Language Language code
     *  @return string Script to create menu into menu bar
     */
    function getMenu($Suspend, $UserName, $UserGroups, $UserLevel,
                     $MenuName = "", $Language = "default") {
        include("dzstonga.inc");
        include("sodebug.inc");

        /* no specific ini stream specified? use default then */
        if ($MenuName == "") $MenuName = dzGetIniPath(DZID_INI_FOLDER)."/menu";

        if (isset($DZ_STONGA_BUTTONS[$Language])) {
            $buttons = &$DZ_STONGA_BUTTONS[$Language];
        } else {
            $buttons = &$DZ_STONGA_BUTTONS["default"];
        };
        if (isset($DZ_CAPTIONS[$Language])) {
            $captions = &$DZ_CAPTIONS[$Language];
        } else {
            $captions = &$DZ_CAPTIONS["default"];
        };

        /* Read in the menu definition from a menu.ini file */
        $this->__setupMenu($UserGroups, $UserLevel, $MenuName, $Language);
        $bg_color = dzGetIniItem(DZCL_SECTION, DZCL_MENU, "app");

        $html = "<HTML><HEAD>\n";
        $html .= "</HEAD><BODY bgcolor=$bg_color><FORM>\n";
        $html .= "<TABLE WIDTH=100% BORDER=0 CELLSPACING=4><TR>\n";
        if (!$Suspend) {
            while (list ($key, $val) = each ($this->MenuStruct)) {
                $html .= "<TD>";
                $itemArr = $val->getAsArray();
                $size = count($itemArr);
                $html .= "<SELECT NAME='$key' SIZE=1 ".
                    "OnChange=\\\"top.nalle.selectWrapper('menu','ENewView',this);\\\">\n";
                $html .= "<OPTION VALUE=''>$key\n";
                $width = $this->__Widths->getItem($key);
                $line = soPadStr("", "-", $width);
                $html .= "<OPTION VALUE=''>$line\n";
                while (list ($title, $file) = each ($itemArr)) {
                    /* Replace underscores with spaces */
                    $title = soSwapStr($title, "_", " ");
                    $html .= "<OPTION VALUE='$file'>$title\n";
                }; // while
                $html .= "</OPTION></SELECT>\n";
                $html .= "</TD>\n";
            }; // while
        } // if

        $caption = $captions[DZSC_LOGINNAME];
        if ($caption == "") $caption = DZSC_LOGINNAME;
        $button = $buttons[DZSE_EXIT];
        if ($button == "") $button = DZSE_EXIT;
        $html .= "<TD>".
                 $captions[DZSC_LOGINNAME].": <B>".$UserName."</B><BR>";

        if (!$Suspend) {
            $html .= "<INPUT TYPE=BUTTON NAME='EExit' VALUE='".
                     $buttons[DZSE_EXIT].
                     "' OnClick=\\\"top.nalle.confirmExit(this);\\\">\n";
        } // if
        $html .="</TD></TR></TABLE>\n";
        $html .= "</FORM></BODY></HTML>";

        /* Add JavaScript that writes the html produced above to the
         * menu bar */
        $result = "MenuPtr = parent.menu.document;\n";
        $scriptLines = soExplode($html, "\n");
        $icount = count($scriptLines);
        for ($c = 0; $c < $icount; $c++) {
            $result .= "MenuPtr.writeln(\"".$scriptLines[$c]."\");\n";
        }
        $result .= "MenuPtr.close();\n";

        $soDebugLevel = SOD_DET;
        $soDebugLogFile = "/tmp/luteet.log";
        soDebug("APUA $result", SOD_DET);
        return $result;
    } // getMenu

}; //dzMenu


/** Data structure that defines the target of the menu action.
 *  There are two posibilies wheter a new browser window is opened
 *  or a new form is opened into Nalle.
 *  Defines also the source for the form or browser window.
 *  Use dzParseMenuTarget()-function to create class of this type
 *  accerding to the menu item definition.
 */
class dzMenuTarget {
    var $Stream;    /*str The source stream */
    var $Target;    /*str The target where the source is opened */
}; // dzMenuTarget


/** Parse menu/subari action target and source stream
 *
 * >$Defintion:str  Menu item definition
 */
function dzParseMenuTarget($Definition) {
    $result = new dzMenuTarget();

    /* Target is the actual target string, but target_type might get tweaked
     * because https and http are considered as just of type http. */
    $target = soExtractVal($Definition, "://", 1);

    /* Replace current protocol tag, if any */
    $protocol = soExtractVal($_SERVER["SERVER_PORT"], "/", 1);
    switch ($protocol) {
        case 80:
            $protocol = "http";
            break;
        case 443:
            $protocol = "https";
            break;
    }; // switch
    $target = str_replace(DZ_CURRENT_PROTOCOL, $protocol, $target);

    /* Sort out the actual target type */
    $target_type = $target;
    $source = soExtractVal($Definition, "://", 2);
    if (ereg(DZMT_EXT_HTTP_FORM.".*", $target_type)) {
        $target_type = DZMT_EXT_HTTP_FORM;
    };

    /* Act accordingly to the target type */
    switch ($target_type) {
        case DZMT_NALLE_FORM:
            $result->Stream = "file://".$source;
            $result->Target = DZMT_NALLE;
            break;

        case DZMT_NALLE_HTTP_FORM:
            $result->Stream = "http://".$source;
            $result->Target = DZMT_NALLE;
            break;

        case DZMT_EXT_FORM:
            $result->Stream = "file://".$source;
            $result->Target = DZMT_EXT_WINDOW;
            break;

        case DZMT_EXT_HTTP_FORM:
            $result->Stream = "$target://".
                              str_replace(DZ_CURRENT_HOST,
                                          $_SERVER["SERVER_NAME"], $source);
            $result->Target = DZMT_EXT_WINDOW;
            break;

        default:
            $result->Stream = $source;
            $result->Target = $target;
    } // switch

    return $result;
}; // dzParseMenuTarget

?>